/**
 * Created by ${PRODUCT_NAME}.
 * User: skylerparr
 * Date: 1/25/11
 * Time: 7:25 PM
 * To change this template use File | Settings | File Templates.
 */
package com.thoughtorigin.meta {
import com.thoughtorigin.flux.Flux;

import com.thoughtorigin.module.ModuleLoader;

import com.thoughtorigin.reflect.MetaReader;

import com.thoughtorigin.util.Instantiator;

import org.flexunit.asserts.assertTrue;
import org.flexunit.asserts.fail;
import org.mockito.integrations.any;
import org.mockito.integrations.between;
import org.mockito.integrations.given;
import org.mockito.integrations.mock;
import org.mockito.integrations.never;
import org.mockito.integrations.useArgument;
import org.mockito.integrations.verify;

[RunWith("org.mockito.integrations.flexunit4.MockitoClassRunner")]
[Mock(type="com.thoughtorigin.module.ModuleLoader")]
[Mock(type="com.thoughtorigin.reflect.MetaReader")]
[Mock(type="com.thoughtorigin.meta.MetadataWorker")]
[Mock(type="com.thoughtorigin.util.Instantiator")]
[Mock(type="com.thoughtorigin.flux.Flux")]
public class MetaReaderWorkerTest {

    private var _readerWorker: MetaReaderWorker;
    private var metaReader: MetaReader;
    private var metaWorker: MetadataWorker;
    private var flux: Flux;
    private var moduleLoader: ModuleLoader;
    private var instantiator: Instantiator;

    [Before]
    public function setUp(): void {
        _readerWorker = new MetaReaderWorker();
        metaReader = mock(MetaReader);
        metaWorker = mock(MetadataWorker);
        flux = mock(Flux);
        moduleLoader = mock(ModuleLoader);
        instantiator = mock(Instantiator);

        given(flux.getProperty("metadataWorker")).willReturn(metaWorker);
    }

    [After]
    public function tearDown(): void {
        _readerWorker = null;
    }

    [Test]
    public function shouldOperateOnMetaData(): void {
        var callbackCalled: Boolean = false;
        var callback: Function = function(): void {
            callbackCalled = true;
            assertTrue(true);

            verify(between(1,1)).that(metaReader.populateMetaData(any(), any()));
            verify(between(1,1)).that(metaWorker.operate(any(), any(), any()));
        }
        var retObj: Object = {};

        given(metaReader.populateMetaData(any(), any())).will(useArgument(1).asFunctionAndCall());
        given(metaWorker.operate(any(), any(), any())).will(useArgument(2).asFunctionAndCall())

        _readerWorker.flux = flux;
        _readerWorker.metaReader = metaReader;
        _readerWorker.operateMetaData(Object, retObj, callback)

        if(!callbackCalled) {
            fail();
        }
    }

    [Test]
    public function shouldInjectClass(): void {
        var callbackCalled: Boolean = false;
        var callback: Function = function(): void {
            callbackCalled = true;
            assertTrue(true);

            verify(between(1,1)).that(metaReader.populateMetaData(any(), any()));
            verify(between(1,1)).that(metaWorker.operate(any(), any(), any()));
            verify(never()).that(moduleLoader.getClassByName(any()));
            verify(between(1,1)).that(instantiator.create(any(),any()));
        }
        var retObj: Object = {};

        given(metaReader.populateMetaData(any(), any())).will(useArgument(1).asFunctionAndCall());
        given(metaWorker.operate(any(), any(), any())).will(useArgument(2).asFunctionAndCall())
        given(moduleLoader.getClassByName(any())).willReturn(retObj);
        given(instantiator.create(any(), any())).willReturn(retObj);

        _readerWorker.flux = flux;
        _readerWorker.metaReader = metaReader;
        _readerWorker.moduleLoader = moduleLoader;
        _readerWorker.instantiator = instantiator;
        _readerWorker.inject(Object, [], callback);

        if(!callbackCalled) {
            fail();
        }
    }

    [Test]
    public function shouldInjectObject(): void {
        var callbackCalled: Boolean = false;
        var callback: Function = function(): void {
            callbackCalled = true;
            assertTrue(true);

            verify(between(1,1)).that(metaReader.populateMetaData(any(), any()));
            verify(between(1,1)).that(metaWorker.operate(any(), any(), any()));
            verify(between(1,1)).that(moduleLoader.getClassByName(any()));
            verify(never()).that(instantiator.create(any(),any()));
        }
        var retObj: Object = {};

        given(metaReader.populateMetaData(any(), any())).will(useArgument(1).asFunctionAndCall());
        given(metaWorker.operate(any(), any(), any())).will(useArgument(2).asFunctionAndCall())
        given(moduleLoader.getClassByName(any())).willReturn(Object);
        given(instantiator.create(any(), any())).willReturn(retObj);

        _readerWorker.flux = flux;
        _readerWorker.metaReader = metaReader;
        _readerWorker.moduleLoader = moduleLoader;
        _readerWorker.instantiator = instantiator;
        _readerWorker.injectObject(retObj, callback);

        if(!callbackCalled) {
            fail();
        }
    }
}
}
